#include <iostream>
#include <omp.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <iostream>

#include "filehandler.h"
#include "quicksort.h"


//#define RAND_RANGE			5
//#define MAX_SIZE			10
#define RAND_RANGE			2000
#define MAX_SIZE			1000000
#define RESULTS_FILE		"result_times.txt"
#define RANDOM_LIST			"random_list.txt"
#define SORTED_NORM_REC		"sorted_list_norm_rec.txt"
#define SORTED_TASK_REC		"sorted_list_task_rec.txt"
#define SORTED_DATA_REC 	"sorted_list_data_rec.txt"
#define SORTED_COMB_REC     "sorted_list_comb_rec.txt"
#define SORTED_NORM_ITER    "sorted_list_norm_iter.txt"
#define SORTED_TASK_ITER    "sorted_list_task_iter.txt"
#define SORTED_DATA_ITER    "sorted_list_data_iter.txt"
#define SORTED_COMB_ITER    "sorted_list_comb_iter.txt"


using namespace std;

int main()
{
    _Results results;

    create_rand_list_file (RAND_RANGE, MAX_SIZE, RANDOM_LIST); //max value of numbers, size of list, name of file

    new_file_line(RESULTS_FILE);

    //Perform recursive quicksort using no decomposition
    int* rec_norm_list = new int[MAX_SIZE];
    fill_array(rec_norm_list, MAX_SIZE, RANDOM_LIST);
    results.quicksortType = "Recursive no decomposition";
    results.start = clock();
    norm_rec_quicksort(rec_norm_list, 0, MAX_SIZE); //performs quicksort algorithm
    results.stop = clock();
    results.total = (double)(results.stop - results.start) / CLOCKS_PER_SEC;
    results.sort = check_sort(rec_norm_list, MAX_SIZE);
    cout << "Results seq rec sort " << (int)results.sort << endl;
    update_file(rec_norm_list, MAX_SIZE, SORTED_NORM_REC); //populates the file with sorted array
    delete [] rec_norm_list;
    populate_results_file(&results, RESULTS_FILE);

    //Perform recursive quicksort using task decomposition
   // int low_limit = 0; //2^5 = 32
    int* rec_task_list = new int[MAX_SIZE];
    fill_array(rec_task_list, MAX_SIZE, RANDOM_LIST);
    results.quicksortType = "Recursive task decomposition";
    results.start = clock();
    task_rec_quicksort(rec_task_list, 0, MAX_SIZE); //performs quicksort algorithm
    results.stop = clock();
    results.total = (double)(results.stop - results.start) / CLOCKS_PER_SEC;
    results.sort = check_sort(rec_task_list, MAX_SIZE);
    cout << "Results task rec sort " << (int)results.sort << endl;
    update_file(rec_task_list, MAX_SIZE, SORTED_TASK_REC); //populates the file with sorted array
    delete [] rec_task_list;
    populate_results_file(&results, RESULTS_FILE);

    //Perform recursive quicksort using data decomposition
    int num_blocks = 10;
    int* rec_data_list = new int[MAX_SIZE];
    fill_array(rec_data_list, MAX_SIZE, RANDOM_LIST);
    results.quicksortType = "Recursive data decomposition";
    results.start = clock();
    data_rec_quicksort(rec_data_list, 0, MAX_SIZE, num_blocks);
    results.stop = clock();
    results.total = (double)(results.stop - results.start) / CLOCKS_PER_SEC;
    results.sort = check_sort(rec_data_list, MAX_SIZE);
    delete [] rec_data_list;
    cout << "Results data rec sort " << (int)results.sort << endl;
    update_file(rec_data_list, MAX_SIZE, SORTED_DATA_REC); //populates the file with sorted array
    populate_results_file(&results, RESULTS_FILE);

    // Perform recursive combination sort
    //int comb_low_limit = 0;
    int comb_num_blocks = 10;
    int* rec_comb_list = new int[MAX_SIZE];
    fill_array(rec_comb_list, MAX_SIZE,RANDOM_LIST);
    results.quicksortType = "Recursive comb decomposition";
    results.start = clock();
    comb_rec_quicksort(rec_comb_list, 0, MAX_SIZE, comb_num_blocks);
    results.stop = clock();
    results.total = (double)(results.stop - results.start) / CLOCKS_PER_SEC;
    results.sort = check_sort(rec_comb_list, MAX_SIZE);
    delete [] rec_comb_list;
    cout << "Results comb rec sort " << (int)results.sort << endl;
    update_file(rec_comb_list, MAX_SIZE, SORTED_COMB_REC); //populates the file with sorted array
    populate_results_file(&results, RESULTS_FILE);

    //Perform iterative quicksort using no decomposition
    int* iter_norm_list = new int[MAX_SIZE];
    fill_array(iter_norm_list, MAX_SIZE, RANDOM_LIST);
    results.quicksortType = "Iterative no decomposition";
    results.start = clock();
    norm_iter_quicksort(iter_norm_list, 0, MAX_SIZE); //performs quicksort algorithm
    results.stop = clock();
    results.total = (double)(results.stop - results.start) / CLOCKS_PER_SEC;
    results.sort = check_sort(iter_norm_list, MAX_SIZE-1);
    cout << "Results seq iter sort " << (int)results.sort << endl;
    update_file(iter_norm_list, MAX_SIZE, SORTED_NORM_ITER); //populates the file with sorted array
    delete [] iter_norm_list;
    populate_results_file(&results, RESULTS_FILE);

    //Perform iterative quicksort using task decomposition
    int* iter_task_list = new int[MAX_SIZE];
    fill_array(iter_task_list, MAX_SIZE, RANDOM_LIST);
    results.quicksortType = "Iterative task decomposition";
    results.start = clock();
    task_iter_quicksort(iter_task_list, 0, MAX_SIZE); //performs quicksort algorithm
    results.stop = clock();
    results.total = (double)(results.stop - results.start) / CLOCKS_PER_SEC;
    results.sort = check_sort(iter_task_list, MAX_SIZE-1);
    cout << "Results task iter sort " << (int)results.sort << endl;
    update_file(iter_task_list, MAX_SIZE, SORTED_TASK_ITER); //populates the file with sorted array
    delete [] iter_task_list;
    populate_results_file(&results, RESULTS_FILE);
    
    //Perform iter quicksort using data decomposition
    int iter_num_blocks = 10;
    int* iter_data_list = new int[MAX_SIZE];
    fill_array(iter_data_list, MAX_SIZE, RANDOM_LIST);
    results.quicksortType = "Iterative data decomposition";
    results.start = clock();
    data_iter_quicksort(iter_data_list, 0, MAX_SIZE, iter_num_blocks);
    results.stop = clock();
    results.total = (double)(results.stop - results.start) / CLOCKS_PER_SEC;
    results.sort = check_sort(iter_data_list, MAX_SIZE);
    delete [] iter_data_list;
    cout << "Results data iter sort " << (int)results.sort << endl;
    update_file(iter_data_list, MAX_SIZE, SORTED_DATA_ITER); //populates the file with sorted array
    populate_results_file(&results, RESULTS_FILE);

    // Perform iterative combination sort
    //int comb_low_limit = 0;
    int iter_comb_num_blocks = 10;
    int* iter_comb_list = new int[MAX_SIZE];
    fill_array(iter_comb_list, MAX_SIZE,RANDOM_LIST);
    results.quicksortType = "Iterative comb decomposition";
    results.start = clock();
    comb_iter_quicksort(iter_comb_list, 0, MAX_SIZE, iter_comb_num_blocks);
    results.stop = clock();
    results.total = (double)(results.stop - results.start) / CLOCKS_PER_SEC;
    results.sort = check_sort(iter_comb_list, MAX_SIZE);
    delete [] iter_comb_list;
    cout << "Results comb iter sort " << (int)results.sort << endl;
    update_file(iter_comb_list, MAX_SIZE, SORTED_COMB_ITER); //populates the file with sorted array
    populate_results_file(&results, RESULTS_FILE);




	return 0;
}
